#ifndef SYNCHRONIZED_QUEUE_HPP
#define SYNCHORNIZED_QUEUE_HPP

#include <queue>
#include <boost/thread.hpp>


template<typename Data>
class SynchronizedQueue
{

private:
	std::queue<Data> queue_;
	mutable boost::mutex mutex_;
	boost::condition_variable conditionVariable_;
public:

    void push(Data const& data)
    {
        boost::mutex::scoped_lock lock(mutex_);
        queue_.push(data);
        lock.unlock();
        conditionVariable_.notify_one();
    }

    bool empty() const
    {
        boost::mutex::scoped_lock lock(mutex_);
        return queue_.empty();
    }

    bool tryToPop(Data& data)
    {
        boost::mutex::scoped_lock lock(mutex_);
        if(queue_.empty())
        {
            return false;
        }
        
        data=queue_.front();
        queue_.pop();
        return true;
    }

    void waitAndPop(Data& data)
    {
        boost::mutex::scoped_lock lock(mutex_);
        while(queue_.empty())
        {
            conditionVariable_.wait(lock);
        }
        
        data=queue_.front();
        queue_.pop();
    }

};

#endif
